#include <errno.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <linux/fs.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/inotify.h>
#include <sys/poll.h>
#include <linux/input.h>
#include <sys/select.h>    
#include <time.h>
#include <signal.h> 
#include <sys/epoll.h>
#include <sys/time.h>
#include <pthread.h>

 
struct RawEvent {
    int32_t when;
    int32_t deviceId;
    int32_t type;
    int32_t code;
    int32_t value;
};
 
void handle_exit(int sig)
{
	//property_set("sys.powerctl", "shutdown");
	system("reboot -p");//重启设备
}
int is_power_down_key(int type, int code, int value)
{
	int is_down = 0;
	is_down = (type == 1) && (code == 116) && (value == 1);
	return is_down;
}
 
int is_power_up_key(int type, int code, int value)
{
	int is_up = 0;
	is_up = (type == 1) && (code == 116) && (value == 0);
	return is_up;
}
 
int main(int argc, char *argv[])
{
	struct itimerval old_value;
	int tap_power_time = 0;
	int tap_power_type = 0;
	int tap_power_code = 0;
	int tap_power_value = 0;
    struct itimerval tick;
	int mEpollFd;
	const int EPOLL_SIZE_HINT = 8;
	const char* DEV_INPUT = "/dev/input/event0";
	struct epoll_event mPendingEventItems[8];
	
	unsigned char buf[1024] = {0};
	struct inotify_event *event = NULL;
	struct RawEvent* readBuffer = (struct RawEvent*) malloc (sizeof(struct RawEvent));
	mEpollFd = epoll_create(EPOLL_SIZE_HINT);
	int fd = open(DEV_INPUT, O_RDWR);
 
	/*
	* struct epoll_event {  
	*	uint32_t events;     // epoll events (bit mask)
	*	epoll_data_t data;   // User data  
	* };  
	*/
	struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
	/**
	* EPOLLIN: has data to read
	* EPOLLOUT: has data to write
	*/
    eventItem.events = EPOLLIN;
 
	/**
	* EPOLL_CTL_ADD: add fd to watching list
	* EPOLL_CTL_DEL: remove fd from watching list
	*/
	if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem) == -1)//检测power按键的fd加入epoll
	{
		printf("add watch failed!\n");
		exit(0);
	}
 
	for (;;)
	{
		/**
		* parameter -1 : wait until event occur ;
		*            0 : return immediately when deal with a non-block event
		*/
		epoll_wait(mEpollFd, mPendingEventItems, 8, -1);
		int32_t readSize = read(fd, readBuffer, sizeof(struct input_event));
		struct input_event *event =(struct input_event*) readBuffer;
 
		//printf("message: t0=%d, t1=%d, type=%d, code=%d, value=%d \n",
					//(int) event->time.tv_sec, (int) event->time.tv_usec,
					//event->type, event->code, event->value);
		tap_power_time = (int) event->time.tv_sec;
		tap_power_type = event->type;
		tap_power_code = event->code;
		tap_power_value = event->value;
 
		/**
		power key event value format:
			got: t0=315898833, t1=723372, type=1, code=116, value=1
			got: t0=315898833, t1=723372, type=0, code=0, value=0
		
			got: t0=315898833, t1=889816, type=1, code=116, value=0
			got: t0=315898833, t1=889816, type=0, code=0, value=0
		*/
 
		if(is_power_down_key(tap_power_type, tap_power_code, tap_power_value))//判断是down还是up
		{
			printf("power down key");
			signal(SIGALRM,handle_exit);
			memset(&tick,0,sizeof(tick));
			tick.it_value.tv_sec= 3;
			tick.it_value.tv_usec= 0;
			setitimer(ITIMER_REAL,&tick,NULL);//起一个3秒定时器，回调函数就是handle_exit,就是重启设备
		}
		else if(is_power_up_key(tap_power_type, tap_power_code, tap_power_value)) 
		{
			tick.it_value.tv_sec= 0;
			tick.it_value.tv_usec= 0;
			setitimer(ITIMER_REAL,&tick,NULL);//取消定时器
		}
		
	}
 
	//remove fd from watching list
	epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, &eventItem);
    return 0;
}
